package shopping

import (
    "strconv"
	"time"
	"dhfshop/models/shopping"
	"dhfshop/models/member"
	"dhfshop/models/isv"
	"dhfshop/models/im"
	"dhfshop/domain/pay"
	"dhfshop/controllers/base"
	"github.com/astaxie/beego/validation"
	"github.com/pkg/errors"
	"github.com/astaxie/beego"
	"dhfshop/domain/member"
	imlayer "dhfshop/domain/im"
)

// 支付管理
type PayController struct {
	base.BaseController
}

func (this *PayController) List() {
    curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
	    this.ServeError("user is not login")
	    return
	}
	appId := this.GetString("app_id")
	if len(appId) < 3 {
		this.ServeError("appId is not invalid")
		return
	}
	acPayParams, err := isv.GetParamsByAppIdOrSubAppId(appId)
	if err != nil {
	   err = errors.Wrap(err, "GetParamsByAppIdOrSubAppId... ")
	   this.ServeError(err.Error())
	}
	rsp := struct {
	    PayWayId  int   `json:"pay_way_id"`
	}{PayWayId:acPayParams.PayWayId}
	this.Data["json"] = rsp
	this.ServeJSON()
}

// 支付方式的选择： 商品在线上，价格准确，则推荐小程序内支付；
// 商品在线下，两种扫码方式由客流量决定
func (this *PayController) PayAdd() {
	var logId int64
	v := struct {
		OrderId  int64  `form:"order_id"  valid:"Required;Min(1)"`
	    PayType  int    `form:"pay_type"`  //0:(缺省)微信;1:支付宝;9:royalpay;10:yabandpay
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return
	}
	//判断订单状态是否: "S_ORDER_WAIT_PAYMENT"
	status, err := shopping.GetOrderStatusById(int64(v.OrderId))
	if err != nil {
	    err = errors.Wrap(err, "GetOrderStatusById... ")
		this.ServeError(err.Error())
		return
	}
	if status != "S_ORDER_WAIT_PAYMENT" {
	    this.ServeError("order status is error")
		return
	}
	order, err := shopping.GetOrderById(int64(v.OrderId))
	if err != nil {
	    err = errors.Wrap(err, "GetOrderById... ")
		this.ServeError(err.Error())
		return
	}
	_, _, err = paylayer.JudgeAndReduceStock(order)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	orderStr := strconv.FormatInt(v.OrderId,10)
	itemTitleArr := []string{}
	for _, item := range order.Items {
		itemTitleArr = append(itemTitleArr, item.Title)
	}
	var person *member.MemberValue
	if person , err = member.GetMemberById(order.MemberId); err != nil {
	    err = errors.Wrap(err, "GetMemberById... ")
		this.ServeError(err.Error())
		return
	}
	var account *member.Account
	if account , err = member.GetAccountById(order.MemberId); err != nil {
	    err = errors.Wrap(err, "GetAccountById... ")
		this.ServeError(err.Error())
		return
	}
	//积分兑换进行支付
	if v.PayType == 100 {
		needIntegral := int(order.Payment*100)
		logId, err = memberlayer.DiscountIntegral(order.PartnerId,order.MemberId,account,needIntegral,orderStr)
		if err == nil {
			//更新订单支付方式编号
			order.PayWayCode = 100
			shopping.UpdateOrderPayWayCode(order)
			//积分兑换支付消息通知
			reqMap := make(map[string]string)
			reqMap["LocalKind"] = "INTEGRAL_PAY"
			reqMap["attach"] = "ESHOP_ORDER_PAY"
			reqMap["out_trade_no"] = orderStr
			imlayer.PushMsgSvrIns.PushDao <- &reqMap
	        //
			rsp := paylayer.PayResponse{BalanceRsp:strconv.FormatInt(logId,10)}
			this.Data["json"] = rsp
			this.ServeJSON()
			return
		}
	}
	//判断订单商品中是否包含支付限制相关字段
	hasLimitPay := isContainLimitPay("no_balance", order)
	if !hasLimitPay {
	    //余额支付
		logId, err = memberlayer.DiscountBalance(order.PartnerId,order.MemberId,account,order.Payment,orderStr)
		if err == nil {
			//更新订单支付方式编号
			order.PayWayCode = 2
			shopping.UpdateOrderPayWayCode(order)
			//余额支付消息通知
			reqMap := make(map[string]string)
			reqMap["LocalKind"] = "BALANCE_PAY"
			reqMap["attach"] = "ESHOP_ORDER_PAY"
			reqMap["out_trade_no"] = orderStr
			imlayer.PushMsgSvrIns.PushDao <- &reqMap
	        //
			rsp := paylayer.PayResponse{BalanceRsp:strconv.FormatInt(logId,10)}
			this.Data["json"] = rsp
			this.ServeJSON()
			return
		}
	}
	prepayId := ""
	var payResponse paylayer.PayResponse
	acPay, err := isv.GetParamsByAppIdOrSubAppId(person.AppId)
	if err != nil {
		err = errors.Wrap(err, "GetParamsByAppIdOrSubAppId... ")
		this.ServeError(err.Error())
		return
	}
	if v.PayType == 9 {
		payResponse, prepayId, err = paylayer.OrderRoyalPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 10 {
		payResponse, prepayId, err = paylayer.OrderYabandPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 11 {
		payResponse, prepayId, err = paylayer.OrderSuperPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 12 {
	    payResponse, prepayId, err = paylayer.OrderUsagms(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 13 {
	    payResponse, prepayId, err = paylayer.OrderDahlPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 14 {
	    payResponse, prepayId, err = paylayer.OrderWiseCashier(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 15 {
	    payResponse, prepayId, err = paylayer.OrderMegaezgoPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}else if v.PayType == 16 {
	    payResponse, prepayId, err = paylayer.OrderChinaUmsPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else if v.PayType == 17 {
	    payResponse, prepayId, err = paylayer.OrderOceanPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else if v.PayType == 18 {
	    payResponse, prepayId, err = paylayer.OrderQcurePay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else if v.PayType == 20 {
	    payResponse, prepayId, err = paylayer.OrderHnaPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else if v.PayType == 21 {
	    payResponse, prepayId, err = paylayer.OrderAllinPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else if v.PayType == 22 {
		payResponse, prepayId, err = paylayer.OrderGpslmallPay(person.AppId,person.OpenID,acPay,order)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
		orderStr = payResponse.OrderId
	}else{
		payResponse, prepayId, err = paylayer.OrderWxPay(person.AppId,person.OpenID,order.StoreId,v.OrderId,acPay,order.Payment)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	}
	if len(prepayId) > 3 {
	    curTime := time.Now().UTC()
		expireTime := curTime.Add(time.Hour*24*7)
		beego.Debug("PayAdd FormIdCache curTime:  expireTime:", curTime, expireTime)
		formIdCache := new(im.FormIdCache)
		formIdCache.PartnerId = order.PartnerId
        formIdCache.MemberId = order.MemberId
        formIdCache.AppId = person.AppId
        formIdCache.FormId = prepayId		
		formIdCache.OpenId = person.OpenID
		formIdCache.Types = "order"
		formIdCache.Xid = orderStr
		formIdCache.MaxCount = 3
		formIdCache.ExpireAt = expireTime
		if _, err := im.AddFormIdCache(formIdCache); err != nil {
		   beego.Debug("AddFormIdCache err:", err.Error())
		}
	}
	this.Data["json"] = payResponse
    this.ServeJSON()	
}

func isContainLimitPay(limitWords string, orders *shopping.ValueOrder) bool {
	hasLimitPay := false
	for _, item := range orders.Items {
	    if item.LimitPay == limitWords {
		    hasLimitPay = true
			break
		}
	}
	return hasLimitPay
}
